home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Cheat II / original / cheatwich.c < prev    next >
Text File  |  1995-01-28  |  18KB  |  725 lines

  1. //    Deals with all the shit that happens when the user interrupts
  2. #include "main.h"
  3. #include "cheat.h"
  4. #include "cheatwich.h"
  5. #include <stdarg.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <Processes.h>
  9. #include <pascal.h>
  10. #include "error.h"
  11. #include <ctype.h>
  12.  
  13. #define charsizeh 6
  14. #define hchars 40
  15. #define charsizev 12
  16. #define vchars 20
  17. #define hsize (charsizeh * hchars)
  18. #define vsize (charsizev * vchars)
  19. #define wintop 40
  20. #define winleft 20
  21. #define hdrawoffset 2
  22. #define vdrawoffset 2
  23.  
  24. #define kmincursorh 2
  25. #define kflashtime 60
  26.  
  27.     // externs
  28.     
  29. long goffset = 0;
  30. long gsearchnum = 0, gnewvalue = 0;
  31. ProcessSerialNumber gplastseen;
  32.  
  33.     // globals
  34.     
  35. long testlong = 739391133;
  36.  
  37. Rect windowBounds = {wintop, winleft, wintop + vsize + vdrawoffset * 2, winleft + hsize + hdrawoffset * 2};
  38. Rect saveBounds = {0, 0, vsize + vdrawoffset * 2, hsize + hdrawoffset * 2 + 8};
  39. static char karz[vchars][hchars];        // note v is first!
  40. static char itch[256];        // if you've got an itch, . . .
  41. int cursor, curflash = 0;
  42. static int lastkey, quitflag;
  43. unsigned long lastflash = 0;
  44. ProcessInfoRec dainfo;
  45. ProcessSerialNumber process;
  46. ProcessSerialNumber lastprocess = {0, 0};
  47.  
  48. Str255 ourtitle, ourcomment;
  49.  
  50. GWorldPtr savepix;
  51.  
  52.  
  53.     // allocate memory for offscreen pixmap
  54. void allocmem(void)
  55. {
  56.     GDHandle            SaveGD;
  57.     CGrafPtr            SavePort;
  58.     OSErr result;
  59.     int a;
  60.     
  61.     GetGWorld(&SavePort, &SaveGD);
  62.     
  63.     result = NewGWorld(&savepix, 8, &saveBounds, 0, nil, 0);
  64.     if (result) {
  65.         stdmessage("\pSorry, not enough memory to start up.");
  66.         verify(false);
  67.     }
  68.     verify(savepix);
  69.     a = LockPixels(savepix->portPixMap);
  70.     verify(a);
  71.     
  72.     SetGWorld(savepix, nil);
  73.     ClipRect(&(*savepix).portRect);
  74.     PaintRect(&(*savepix).portRect);
  75.     
  76.     SetGWorld(SavePort, SaveGD);
  77. }
  78.  
  79. unsigned char kmp[16];
  80.  
  81.     // k =  any keyboard scan code, 0-127
  82. static int isPressed(unsigned short k )
  83. {
  84.     return ( ( kmp[k>>3] >> (k & 7) ) & 1);
  85. }
  86.  
  87. static void clearkarz(void)
  88. {
  89.     int i, j;
  90.     for (i=0;i<hchars;i++) for (j=0;j<vchars;j++) karz[j][i] = ' ';
  91. }
  92.  
  93. static void drawrow(int v)
  94. {
  95.     int i, y = (vchars - v) * charsizev - vdrawoffset;
  96.     Rect r;
  97.  
  98.     SetRect(&r, 0, y - charsizev + 3, hsize + 10, y + 3);
  99.     EraseRect(&r);
  100.     for (i=0;i<hchars;i++) {
  101.         MoveTo(i * charsizeh + hdrawoffset, y);
  102.         DrawChar(karz[v][i]);
  103.     }
  104. }
  105.  
  106. static void drawcell(int h)
  107. {
  108.     int y = (vchars) * charsizev - vdrawoffset;
  109.     Rect r;
  110.  
  111.     SetRect(&r, hdrawoffset + cursor * charsizeh, y - charsizev + 3, hdrawoffset + (cursor+1) * charsizeh, y + 3);
  112.     EraseRect(&r);
  113.     MoveTo(h * charsizeh + hdrawoffset, y);
  114.     DrawChar(karz[0][h]);
  115. }
  116.  
  117. static void newprompt(void)
  118. {
  119.     int i;
  120.     for (i=0;i<hchars;i++) karz[0][i] = ' ';
  121.     karz[0][0] = '>';
  122.     drawrow(0);
  123.     cursor = kmincursorh;
  124. }
  125.  
  126. static void scrollit(void)
  127. {
  128.     int i, j;
  129.     for (j=vchars-1;j>=1;j--)
  130.         for (i=0;i<hchars;i++)
  131.             karz[j][i] = karz[j-1][i];
  132.     for (i=0;i<hchars;i++) karz[0][i] = ' ';
  133.     for (j=0;j<vchars;j++)
  134.         drawrow(j);
  135.     cursor = 0;
  136. }
  137.  
  138. static void cprintf(char *fmt, ...)
  139. {
  140.     va_list args;
  141.     int len, cur = 0, ph;
  142.     
  143.     va_start(args, fmt);
  144.     
  145.     len = vsprintf(itch, fmt, args);
  146.     
  147.     do {
  148.         ph = cursor;
  149.         for (;(cur < len);cur++)
  150.             if (ph >= hchars) {
  151.                 scrollit();
  152.                 ph = 0;
  153.                 break;            
  154.             }
  155.             else if (itch[cur] == '\n') {
  156.                 scrollit();
  157.                 cur++;
  158.                 ph = 0;
  159.                 break;
  160.             }
  161.             else
  162.                 karz[0][ph++] = itch[cur];
  163.     } while (cur < len);
  164.     cursor = ph;
  165.     drawrow(0);
  166.     
  167.     va_end(args);
  168. }
  169.  
  170. static void printprocess(void)
  171. {
  172.     char nm[32];
  173.     OSErr err;
  174.     Boolean res;
  175.  
  176.     if (GetFrontProcess(&process) != noErr)
  177.         return;
  178.     
  179.         // clear things up if this isn't the same process
  180.     err = SameProcess(&process, &lastprocess, &res);
  181.     if (err || !res) {
  182.         goffset = 0;
  183.         gsearchnum = 0; gnewvalue = 0;
  184.     }
  185.     BlockMove(&process, &lastprocess, sizeof(ProcessSerialNumber));
  186.     
  187.     dainfo.processInfoLength = sizeof(ProcessInfoRec);
  188.     dainfo.processName = (void *) nm;
  189.     dainfo.processAppSpec = 0;
  190.     
  191.     if (GetProcessInformation(&process, &dainfo) != noErr) 
  192.         return;
  193.     nm[nm[0]+1] = 0;
  194.     cprintf("We've stopped in %s\n", &nm[1]);        // output the name
  195. }
  196.  
  197. static void printstatus(void)
  198. {
  199.     cprintf("Search size: %s, ", (gvalsize == ksizelong) ? "long" :
  200.         ((gvalsize == ksizeint) ? "integer" : "byte"));
  201.     cprintf("Search value: %ld, Possibilities: %ld,",
  202.         gsearchnum, gcurposs);
  203.     cprintf(" Offset: %ld,", goffset);
  204.     cprintf(" Change to: %ld\n", gnewvalue);
  205. }
  206.  
  207. static void flashcursor(int turnoff)
  208. {
  209.     Rect r;
  210.     int y = vchars * charsizev - vdrawoffset;
  211.  
  212.     SetRect(&r, hdrawoffset + cursor * charsizeh, y - charsizev + 3, hdrawoffset + (cursor+1) * charsizeh, y);
  213.     if (TickCount() - lastflash >= kflashtime) {
  214.         curflash = !curflash;
  215.         lastflash = TickCount();
  216.     }
  217.     if (turnoff || !curflash)
  218.         EraseRect(&r);
  219.     else
  220.         PaintRect(&r);
  221. }
  222.  
  223.     // the user hit the search button, so let's do it
  224. static void processsearch(void)
  225. {
  226.     int *pint, findint, temp;
  227.     void *p;
  228.     long endsearch, findlong, newposs, *plong, l, startsearch;
  229.     Str255 str;
  230.     
  231.         // get the number to search for
  232.     findlong = gsearchnum;
  233.     findint = findlong;
  234.  
  235.     p = (void *) ((long) dainfo.processLocation + dainfo.processSize);
  236.     startsearch = (long) p;
  237.     if (!gcurposs) {    // starting a new search
  238.             // p is start of search, at the largest location in that app's partition
  239.         endsearch = (long) dainfo.processLocation;
  240.         pint = (int *) p; plong = (long *) p;
  241.         
  242.         switch (gvalsize) {
  243.             case ksizelong:
  244.                 while ((long) plong >= endsearch) {
  245.                     plong = (long *) ((long) plong - 2);    // only decrement two bytes
  246.                     if (*plong == findlong) {        // we've found a possibility
  247.                         gposs[gcurposs++] = (Ptr) plong;    // store it
  248.                         if (gcurposs>=gmaxposs)        // too many values
  249.                             plong = (void *) (endsearch-4);        // this will kill the search
  250.                     }
  251.                 }
  252.                 break;
  253.             case ksizeint:
  254.                 while ((long) pint >= endsearch)
  255.                     if (*--pint == findint) {        // we've found a possibility
  256.                         gposs[gcurposs++] = (Ptr) pint;    // store it
  257.                         if (gcurposs>=gmaxposs)        // too many values
  258.                             pint = (void *) (endsearch-4);        // this will kill the search
  259.                     }
  260.                 break;
  261.             case ksizebyte:
  262.                 while ((long) pint >= endsearch) {
  263.                     pint--;
  264.                         // first look at high-order byte
  265.                     temp = (*pint) >> 8;
  266.                     if (temp == findint) {        // we've found a possibility
  267.                         gposs[gcurposs++] = (Ptr) pint;    // store it
  268.                         if (gcurposs>=gmaxposs)        // too many values
  269.                             pint = (void *) (endsearch-4);        // this will kill the search
  270.                     }
  271.                         // now look at low-order byte
  272.                     temp = (*pint) & 0xFF;
  273.                     if (temp == findint) {        // we've found a possibility
  274.                         gposs[gcurposs++] = (Ptr) ((long) pint + 1);    // store it
  275.                         if (gcurposs>=gmaxposs)        // too many values
  276.                             pint = (void *) (endsearch-4);        // this will kill the search
  277.                     }
  278.                 }
  279.                 break;
  280.             default: break;
  281.         }
  282.     }
  283.     else {        // refining a search
  284.         newposs = 0;
  285.         switch (gvalsize) {
  286.             case ksizelong:        // we're dealing in longints
  287.                 for (l=0;l<gcurposs;l++)
  288.                     if (*((long *)gposs[l]) == findlong)
  289.                         gposs[newposs++] = gposs[l];
  290.                 break;
  291.             case ksizeint:        // we're dealing in integers
  292.                 for (l=0;l<gcurposs;l++)
  293.                     if (*((int *)gposs[l]) == findint)
  294.                         gposs[newposs++] = gposs[l];
  295.                 break;
  296.             case ksizebyte:        // we're dealing in bytes
  297.                 for (l=0;l<gcurposs;l++)
  298.                     if ((long) gposs[l] & 1) {    // some are odd
  299.                             // extract low order byte
  300.                         if ((*((int *)((long) gposs[l] - 1)) & 0xFF) == findint)
  301.                             gposs[newposs++] = gposs[l];
  302.                     }
  303.                     else if ((*((int *)gposs[l]) >> 8) == findint)
  304.                         gposs[newposs++] = gposs[l];
  305.                 break;
  306.             default: break;
  307.         }
  308.         gcurposs = newposs;
  309.     }
  310.     
  311.         // change the text field of the possibilities item
  312.     if (gcurposs)
  313.         goffset = startsearch - (long) gposs[0];
  314.     else
  315.         goffset = 0;
  316.         
  317.     cprintf("Possibilities: %ld\n", gcurposs);
  318. }
  319.  
  320.  
  321.     // called when a user types change
  322. static void processchange(void)
  323. {
  324.     Str255 str;
  325.     int changeto, *ip, temp;
  326.     short res;
  327.  
  328.     if (goffset == 0) {
  329.         cprintf("Error: offset of 0 cannot be valid");
  330.         return;
  331.     }
  332.     if (gcurposs>1)
  333.         cprintf("(* warning, value changed without unique location *)\n");
  334.     changeto = gnewvalue;
  335.     switch (gvalsize) {
  336.         case ksizelong:        // we're dealing in longints
  337.             *((long *) gposs[0]) = gnewvalue;        // set the place in memory!
  338.             break;
  339.         case ksizeint:        // we're dealing in integers
  340.             if (gnewvalue > 65535) {
  341.                 cprintf("Error: Change To value is too large for integer.\n");
  342.                 return;
  343.             }
  344.             *((int *) gposs[0]) = changeto;        // set the place in memory!
  345.             break;
  346.         case ksizebyte:
  347.             if (gnewvalue > 255) {
  348.                 cprintf("Error: Change To value is too large for byte.\n");
  349.                 return;
  350.             }
  351.             if ((long) gposs[0] & 1) {        // odd address
  352.                 ip = (int *) ((long) gposs[0] - 1);        // set at word right before byte
  353.                     // change the low-order byte of this word to what we want
  354.                 temp = (((*ip) >> 8) << 8) + (changeto & 0xFF);
  355.                 *ip = temp;        // set it in memory
  356.             }
  357.             else {
  358.                 ip = (int *) gposs[0];        // treat as word pointer
  359.                     // change the high-order byte of this word to what we want
  360.                 temp = (((*ip) << 8) >> 8) + ((changeto & 0xFF) << 8);
  361.                 *ip = temp;        // set it in memory
  362.             }
  363.             break;
  364.         default: cprintf("error!\n"); break;
  365.     }
  366. }
  367.  
  368.     // they want to change search value
  369. static void processvalue(char *c, int len)
  370. {
  371.     c += len - 1;    // put on last char of command
  372.     while (*++c == ' ');        // skip spaces
  373.     if (*c == '\0') {
  374.         cprintf("You must supply a value, chump.\n");
  375.         return;
  376.     }
  377.         // finally get the value
  378.     gsearchnum = atol(c);
  379.     cprintf("Search value: %ld\n", gsearchnum);
  380. }
  381.  
  382.     // they want to change the offset, highly riskeeeeeee
  383. static void processoffset(char *c, int len)
  384. {
  385.     c += len - 1;    // put on last char of command
  386.     while (*++c == ' ');        // skip spaces
  387.     if (*c == '\0') {
  388.         cprintf("You must supply a value, chump.\n");
  389.         return;
  390.     }
  391.         // finally get the value
  392.     goffset = atol(c);
  393.     cprintf("New offset: %ld\n", goffset);
  394. }
  395.  
  396.     // they want to change the change value
  397. static void processchangevalue(char *c, int len)
  398. {
  399.     c += len - 1;    // put on last char of command
  400.     while (*++c == ' ');        // skip spaces
  401.     if (*c == '\0') {
  402.         cprintf("You must supply a value, wizard.\n");
  403.         return;
  404.     }
  405.         // finally get the value
  406.     gnewvalue = atol(c);
  407.     cprintf("Change value: %ld\n", gnewvalue);
  408. }
  409.  
  410.  
  411.     // they want to start over, tabula rasa
  412. static void processstartover(void)
  413. {
  414.     gcurposs = 0;
  415.     goffset = 0;
  416. }
  417.  
  418.     // they want to save their cheat
  419. static void processsave(void)
  420. {
  421.     int i;
  422.     
  423.     if (numwichcuts == kmaxwichcuts) {
  424.         cprintf("Error saving: too many cheats have been saved.  Return to application\
  425.             to save more. (Sorry.)\n");
  426.         return;
  427.     }
  428.     if (!ourtitle[0]) {
  429.         cprintf("Error saving: you must supply a title\n");
  430.         return;
  431.     }
  432.     if (goffset>150000)
  433.         cprintf("(* warning, value saved is reasonably likely to move about, thus saved position may not work again *)\n");
  434.     wichcuts[numwichcuts].offset = goffset;
  435.     wichcuts[numwichcuts].datasize = gvalsize;
  436.     wichcuts[numwichcuts].newval = gnewvalue;
  437.     for (i=0;i<100;i++) {
  438.         wichcuts[numwichcuts].title[i] = ourtitle[i];
  439.         wichcuts[numwichcuts].comment[i] = ourcomment[i];
  440.     }
  441.     
  442.     numwichcuts++;        // we just added one
  443. }
  444.  
  445.     // returns true if strings are equal (ignoring case)
  446. static int eqstring(char *c, Str255 s)
  447. {
  448.     int i = 1;
  449.     
  450.     while (*c)
  451.         if (*c++ != toupper(s[i++]))
  452.             return false;
  453.     return true;
  454. }
  455.  
  456.     // they want to open a saved shortcut
  457. static void processopen(char *c, int len)
  458. {
  459.     int i;
  460.     shortcut sc;
  461.     
  462.     if (!len) {
  463.         cprintf("Error opening: you must supply a title\n");
  464.         return;
  465.     }
  466.     c += 5;
  467.     sc.title[0] = 0;
  468.         // find the shortcut with the given title
  469.         // first look in shit we just did
  470.     for (i=0;i<numwichcuts;i++)
  471.         if (eqstring(c, wichcuts[i].title)) {
  472.             sc = wichcuts[i];
  473.             break;
  474.         }
  475.         // now look in the main list
  476.     HLock((Handle) cut);
  477.     if (i == numwichcuts)    // only if not already found
  478.         for (i=0;i<gnumcuts;i++)
  479.             if (eqstring(c, (*cut)[i].title)) {
  480.                 sc = (*cut)[i];
  481.                 break;
  482.             }
  483.     HUnlock((Handle) cut);
  484.     if (!sc.title[0]) {
  485.         cprintf("Error opening: cheat could not be found\n");
  486.         return;
  487.     }
  488.     cprintf("Cheat opened\n");
  489.     goffset = sc.offset;
  490.     if (goffset>150000)
  491.         cprintf("(* warning, there's a good chance this cheat will not work, and might also crash the program *)\n");
  492.     gvalsize = sc.datasize;
  493.     gnewvalue = sc.newval;
  494.     for (i=0;i<254;i++) {
  495.         ourtitle[i] = sc.title[i];
  496.         ourcomment[i] = sc.comment[i];
  497.     }
  498.     gcurposs = 1;
  499. }
  500.  
  501.  
  502.     // they want to change size of datum for which they are searching
  503. static void processsize(char *c, int len)
  504. {
  505.     c += len - 1;    // put on last char of command
  506.     while (*++c == ' ');        // skip spaces
  507.     if (*c == '\0') {
  508.         cprintf("You must supply a value, bud.\n");
  509.         return;
  510.     }
  511.         // finally get the value, switch the first char of the word
  512.     switch (*c) {
  513.         case 'B': gvalsize = ksizebyte; break;
  514.         case 'I': gvalsize = ksizeint; break;
  515.         case 'L': gvalsize = ksizelong; break;
  516.         default:
  517.             cprintf("Not a valid size.\n");
  518.             return;
  519.             break;
  520.     }
  521.     cprintf("Search size: %s\n", (gvalsize == ksizelong) ? "long" :
  522.         ((gvalsize == ksizeint) ? "integer" : "byte"));
  523. }
  524.  
  525.     // they want to change size of datum for which they are searching
  526. static void processtitle(char *c, int len)
  527. {
  528.     char ch;
  529.         
  530.     c += len - 1;    // put on last char of command
  531.     while (*++c == ' ');        // skip spaces
  532.     strcpy((char *) ourtitle, c);
  533.     cprintf("Title set to %s\n", (char *) ourtitle);
  534.     (void) CtoPstr((char *) ourtitle);
  535. }
  536.  
  537.     // they want to change size of datum for which they are searching
  538. static void processcomment(char *c, int len)
  539. {
  540.     char ch;
  541.         
  542.     c += len - 1;    // put on last char of command
  543.     while (*++c == ' ');        // skip spaces
  544.     strcpy((char *) ourcomment, c);
  545.     cprintf("Comment set to %s\n", (char *) ourcomment);
  546.     (void) CtoPstr((char *) ourcomment);
  547. }
  548.  
  549.  
  550. static void processline(char *c)
  551. #define checkcom(shouldbe) (((long) strstr(c, shouldbe) == (long) c) && (len = strlen(shouldbe)))
  552. {
  553.     int len;
  554.     
  555.     if (checkcom("QUIT"))
  556.         quitflag = true;
  557.     else if (checkcom("STATUS") || checkcom("SS"))
  558.         printstatus();
  559.     else if (checkcom("SEARCHVALUE") || checkcom("SV"))
  560.         processvalue(c, len);
  561.     else if (checkcom("OFFSET"))
  562.         processoffset(c, len);
  563.     else if (checkcom("CHANGEVALUE") || checkcom("CV"))
  564.         processchangevalue(c, len);
  565.     else if (checkcom("SEARCH") || checkcom("SH")) {
  566.         processsearch();
  567.         printstatus();
  568.     }
  569.     else if (checkcom("SIZE"))
  570.         processsize(c, len);
  571.     else if (checkcom("TITLE"))
  572.         processtitle(c, len);
  573.     else if (checkcom("COMMENT"))
  574.         processcomment(c, len);
  575.     else if (checkcom("SAVE"))
  576.         processsave();
  577.     else if (checkcom("OPEN"))
  578.         processopen(c, len);
  579.     else if (checkcom("CHANGE") || checkcom("CE"))
  580.         processchange();
  581.     else if (checkcom("STARTOVER") || checkcom("SO"))
  582.         processstartover();
  583.     else if (checkcom("HELP")) {
  584.         len = strlen(c);
  585.         if (len > 4) {
  586.             c += 5;        // advance past "HELP"
  587.             if (checkcom("SIZE"))
  588.                 cprintf("SIZE x; where x is either LONGINT (L), INTEGER (I), or BYTE (B)\n");
  589.             else if (checkcom("SEARCHVALUE"))
  590.                 cprintf("SEARCHVALUE x; where x is the number to search for\n");
  591.             else if (checkcom("CHANGEVALUE"))
  592.                 cprintf("CHANGEVALUE x; where x is the new number to change to\n");
  593.             else if (checkcom("OPEN"))
  594.                 cprintf("OPEN f; where f is the name of the Cheat, listed in Cheat Sheet window\n");
  595.         }
  596.         else {
  597.             cprintf("the valid comands are:\n");
  598.             cprintf("QUIT, STATUS (SS), SIZE, SEARCH (SH), STARTOVER (SO), SEARCHVALUE (SV),\
  599.                  CHANGEVALUE (CV), CHANGE (CE), OPEN, SAVE, TITLE, COMMENT\n");
  600.             cprintf("type 'HELP subject' to get more specific help in following subjects:\n");
  601.             cprintf("SIZE, SEARCHVALUE, CHANGEVALUE, OPEN");
  602.         }
  603.     }
  604.     else
  605.         cprintf("Not a command.  Sorry champ.\n");        
  606. }
  607.  
  608.     // the character strings for char code equivs, yuch
  609. #define knumchars 0x38
  610. const char (keychar[knumchars]) = {
  611. 'A', 'S', 'D', 'F', 'H', 'G', 'Z', 'X',
  612. 'C', 'V', '\0', 'B', 'Q', 'W', 'E', 'R',
  613. 'Y', 'T', '1', '2', '3', '4', '6', '5',
  614. '=', '9', '7', '-', '8', '0', ']', 'O',
  615. 'U', '[', 'I', 'P', '\x0D', 'L', 'J', '\0',
  616. 'K', ';', '\\', ',', '/', 'N', 'M', '.',
  617. '\0', ' ', '\0', '\x01', '\0', '\0', '\0', '\0'        // 38
  618. };
  619.  
  620. static void keycheck(long oldtrap)
  621. {
  622.     int i, code, j, oc;
  623.     
  624.     if (!oldtrap)        // we're testing or somesuch
  625.         GetKeys((long *) kmp);
  626.     else
  627.         CallPascal((long *) kmp, oldtrap);
  628.     code = -1;
  629.     for (i=0;i<16;i++)
  630.         if (kmp[i]) {
  631.             for (j=0;j<=7;j++)
  632.                 if ((kmp[i]>>j)&1)
  633.                     if ((i*8 + j) <= 0x70)
  634.                         code = i * 8 + j;
  635.         }
  636.     if (code == lastkey)
  637.         return;        // hasn't lifted up key yet
  638.     lastkey = code;
  639.     if ((code >= 0) && (code < knumchars) && keychar[code]) {
  640.         if (keychar[code] == 0x01) {        // delete
  641.             if (cursor > kmincursorh) {        // can't delete too much
  642.                 drawcell(cursor);
  643.                 cursor--;
  644.                 karz[0][cursor] = ' ';
  645.                 drawcell(cursor);
  646.                 curflash = 0;
  647.                 lastflash = 0;
  648.             }
  649.         }
  650.         else if (keychar[code] == 0x0D) {    // return
  651.             oc = cursor;
  652.             scrollit();
  653.             karz[1][oc] = '\0';
  654.             processline(&karz[1][2]);    // it's been scrolled up
  655.             karz[1][oc] = ' ';
  656.             newprompt();
  657.         }
  658.         else if (cursor < hchars-1) {
  659.             karz[0][cursor] = keychar[code];
  660.             drawcell(cursor);
  661.             cursor++;
  662.             curflash = 0;
  663.             lastflash = 0;
  664.         }
  665.     }
  666. }
  667.  
  668. static void mainloop(long oldtrap)
  669. {
  670.     int k;
  671.     
  672.     lastkey = -1;
  673.     quitflag = 0;    
  674.     
  675.     clearkarz();
  676.     printprocess();
  677.     shouldclearup = true;
  678.     printstatus();
  679.     cprintf("type 'HELP' for more help\n");
  680.     newprompt();
  681.     while (!quitflag) {
  682.         flashcursor(false);
  683.         keycheck(oldtrap);
  684.     }
  685. }
  686.  
  687. int cheatwich(long oldtrap)
  688. {
  689.     GDHandle            SaveGD;
  690.     CGrafPtr            SavePort;
  691.     WindowPtr wichWindow, frontone;
  692.     CGrafPort daport;
  693.     
  694.     GetGWorld(&SavePort, &SaveGD);
  695. /*    frontone = FrontWindow();
  696.     wichWindow = NewWindow(0L, &windowBounds, "\p", true, altDBoxProc, (WindowPtr) -1L, false, 0);
  697.     if (!wichWindow)
  698.         return false;
  699.     SetPort(wichWindow); */
  700.     OpenCPort(&daport);
  701.     
  702.         // save the contents of this part of screen into GWorld
  703.     SetGWorld(savepix, nil);
  704.     CopyBits ((BitMap *) *(daport.portPixMap), (BitMap *) *(savepix->portPixMap),
  705.         &saveBounds, &saveBounds, srcCopy, nil);
  706.     SetGWorld(&daport, nil);
  707.  
  708.     TextFont(monaco);
  709.     TextSize(9);
  710.     
  711.     mainloop(oldtrap);
  712.  
  713. //    DisposeWindow(wichWindow);
  714. //    if (frontone)
  715. //        BringToFront(frontone);
  716.  
  717.     CopyBits ((BitMap *) *(savepix->portPixMap), (BitMap *) *(daport.portPixMap),
  718.         &saveBounds, &saveBounds, srcCopy, nil);
  719.  
  720.     CloseCPort(&daport);
  721.     SetGWorld(SavePort, SaveGD);
  722.     
  723.     FlushEvents(everyEvent, 0);
  724.     return true;        // all okay
  725. }